#pragma once

#include <string>
#include <map>
#include <mutex>

using namespace std;

#include "logcplus_common.h"
#include "logcplus_base_writer.h"
#include "logcplus_properties.h"

namespace logcplus
{
    class CLogger
    {
    private:
        logcplus_params m_params;
        logcplus_base_writer* m_pLogger;
        std::string m_suffix;
        pthread_t m_ttid;
        std::string m_reserved;
    public:
        CLogger();
        CLogger(logcplus_type_t logtype);
        virtual  ~CLogger();
        bool IsOpen();

        int   SetLogParams(const string& logger_name,logcplus_properties& attrs,const string& suffix=string());
        int   SetLogParams(const logcplus_params& params,const string& suffix=string());    
        int   SetLogParams(const string& logcplus_config_file,const string& logger_name=string());

        void  SetLogType(logcplus_type_t log_type);
        void  SetLogLevel(logcplus_level_t log_level);
        void  SetLogName(const string& sLogName);
        void  SetTagName(const string& sTagName );
        void  SetLogFileMaxSize(long iMaxLogFileSize);
        void  SetLogFileMaxNums(int iMaxLogFileNums); 
        void  SetBufferFlag(logcplus_buffer_level_t buffer_level) ;
        void  SetLogLayout(const string& sLayout);
        void  SetLogFileDir(const string& sLogFileDir) ;
        void  SetLogTid();
        void  SetLogSaveDays(int days);
        void  SetLogReserved(const string& sReserved);

        bool IsEnabledFor(int level);

        string    GetLogName();
        uint16_t  GetLogLevel();
        uint64_t  GetLogNbr();
        pthread_t GetLogTid();
    public:
        int  LogInit();
        int  LogInit(const string& sLogName, int Level);
        int  LogBegin(uint64_t logMsgId = 0);
        void LogWrite(const char* File, const char* Function, int Line,  int Level,const char* LogMsg);
        void LogWrite(const char* sLogText,int Level=0);
        void LogCommit();
        void LogUInit();

        void Trace(  const char* File, const char* Function, int Line,  const char* Fmt, ...);
        void Debug(  const char* File, const char* Function, int Line,  const char* Fmt, ...);
        void Info(   const char* File, const char* Function, int Line,  const char* Fmt, ...);
        void Warn(   const char* File, const char* Function, int Line,  const char* Fmt, ...);
        void Error(  const char* File, const char* Function, int Line,  const char* Fmt, ...);
        void Fatal(  const char* File, const char* Function, int Line,  const char* Fmt, ...);    

        void Logger( const char* File, const char* Function, int Line,  int Level, const char* Fmt, ...);
        void LogHex( const char* File, const char* Function, int Line,  int Level, const char* LogMsg, int Length);
    private:
        static std::mutex  m_lock; 
        class AutoRelease
        {
        public:
            ~AutoRelease()
            {
                if (CLogger::m_instance)
                {
                    std::lock_guard<std::mutex> _lock(m_lock);
                    delete CLogger::m_instance;
                    CLogger::m_instance = nullptr;
                }
                if(CLogger::m_mutil_instance.size() > 0)
                {
                    std::lock_guard<std::mutex> _lock(m_lock);
                    for(auto it = CLogger::m_mutil_instance.begin(); it != CLogger::m_mutil_instance.end();)
                    {
                        delete it->second;
                        it->second = nullptr;
                        CLogger::m_mutil_instance.erase(it++);
                    }
                }
            };
        };
        static CLogger* m_instance;
        static AutoRelease m_release;    
        static std::map<string,CLogger*> m_mutil_instance;
    public:
        static CLogger* getInstance(const string& instanceName="");	
    };

    struct LoggerUtil
    {
    public:    
        static CLogger* GetInstance(const string& instanceName);
        static CLogger* GetInstance();
    private:    
        static CLogger*  pLogger;
    };    
}  
